#include <assert.h>
#include "../include/MsgQueue.h"

namespace ZY {

    map<int, MsgQueue*> MsgQueue::_i_instances;
    map<string, MsgQueue*> MsgQueue::_s_instances;

    MsgQueue::MsgQueue()
    {
        //ctor
        pthread_mutex_init( & lock , NULL );
    }

    MsgQueue::~MsgQueue()
    {
        //dtor
        pthread_mutex_destroy( & lock );
    }

    MsgQueue &MsgQueue::getInstance( string instanceName )
    {
        if ( _s_instances.count( instanceName ) == 0 ) {
            _s_instances[ instanceName ] = new MsgQueue();
        }
        return * (_s_instances[ instanceName ] );
    }


    MsgQueue &MsgQueue::getInstance( int instanceId )
    {
        if ( _i_instances.count( instanceId ) == 0 ) {
            _i_instances[ instanceId ] = new MsgQueue();
        }

        MsgQueue *p = _i_instances[ instanceId ] ;
        assert( p );
        return * ( p );
    }

    void MsgQueue::destroyInstance( string instanceName )
    {
        if ( _s_instances.count( instanceName ) == 0 ) {
            return;
        }

        delete _s_instances[ instanceName ];
        _s_instances.erase( instanceName );
    }

    void MsgQueue::destroyInstance( int instanceId )
    {
        if ( _i_instances.count( instanceId ) == 0 ) {
            return;
        }
        delete _i_instances[ instanceId ];
        _i_instances.erase( instanceId );
    }

    void MsgQueue::add( MsgQueue::CallbackFn fn )
    {
        sMsgQueueData *smd;

        smd = new sMsgQueueData();

        //smd->ext = NULL;
        smd->fn = fn;

        _queue.push_back( smd );
    }
    void MsgQueue::add( MsgQueue::CallbackFn fn , ByteString & ext_data )
    {
        sMsgQueueData *smd;

        smd = new sMsgQueueData();
        smd->ext.copyFrom( ext_data );
        smd->fn = ( MsgQueue::CallbackFn ) fn;

        _queue.push_back( smd );
    }

    bool MsgQueue::run_front()
    {
        if ( _queue.size() == 0 ) {
            return false;
        }


        sMsgQueueData *data;
        data = _queue.front();
        if(data->fn){
            data->fn( data->ext );
        }

        _queue.pop_front();

        delete data;

        return true;
    }

    void MsgQueue::swap( MsgQueue &m )
    {
        _queue.swap( m._queue );
    }

    bool MsgQueue::merginTo( MsgQueue & m )
    {
        if ( pthread_mutex_trylock( & m.lock ) != 0 ) {
            return false;
        }
        m._queue.splice( m._queue.end() , _queue , _queue.begin() , _queue.end() );
        pthread_mutex_unlock( & m.lock );
        return true;
    }

    bool MsgQueue::blockMerginTo(MsgQueue& m)
    {
        pthread_mutex_lock( & m.lock ) ;
        m._queue.splice( m._queue.end() , _queue , _queue.begin() , _queue.end() );
        pthread_mutex_unlock( & m.lock );
        return true;
    }

    bool MsgQueue::merginFrom( MsgQueue & m )
    {
        if ( pthread_mutex_trylock( & m.lock ) != 0 ) {
            return false;
        }
        _queue.splice( _queue.end() , m._queue , m._queue.begin() , m._queue.end() );
        pthread_mutex_unlock( & m.lock );
        return true;
    }
}
